#pragma once

namespace gp
{
	class ParameterBlockContainer
	{
	public:

		ParameterBlockContainer(ParameterBlockHandle* pParameterBlocks, cr::size_t maxParameterBlocks)
		: m_pParameterBlocks(pParameterBlocks)
		, m_numParameterBlocks(0)
		, m_maxParameterBlocks(maxParameterBlocks)
		{
		}

		cr::size_t						GetNumParameterBlocks() const
		{
			return m_numParameterBlocks;
		}

		ParameterBlockHandle			GetParameterBlock(cr::size_t idxParameterBlock)
		{
			CR_ASSERT(idxParameterBlock < m_numParameterBlocks);
			return m_pParameterBlocks[idxParameterBlock];
		}

		void							PushParameterBlock(ParameterBlockHandle hParameterBlock)
		{
			CR_ASSERT_MSG(m_numParameterBlocks < m_maxParameterBlocks, "Parameter block container is full");
			m_pParameterBlocks[m_numParameterBlocks++] = hParameterBlock;
		}

		void							PopParameterBlock()
		{
			CR_ASSERT_MSG(m_numParameterBlocks > 0, "Parameter block container is empty");
			m_pParameterBlocks[m_numParameterBlocks-1] = 0;
			m_numParameterBlocks--;
		}

	protected:

		ParameterBlockHandle*			m_pParameterBlocks;
		cr::size_t						m_numParameterBlocks;
		cr::size_t						m_maxParameterBlocks;
	};

	typedef cr::Handle<ParameterBlockContainer> ParameterBlockContainerHandle;
	typedef cr::Handle<const ParameterBlockContainer> ParameterBlockContainerConstHandle;

	// ---------------------------------------------------------------------------------------------------------

	template <cr::size_t MAX_PARAMETER_BLOCKS>
	class ParameterBlockContainerFixed : public ParameterBlockContainer
	{
	public:

		ParameterBlockContainerFixed()
		: ParameterBlockContainer(m_parameterBlocks, MAX_PARAMETER_BLOCKS)
		{
		}

	private:

		ParameterBlockHandle	m_parameterBlocks[MAX_PARAMETER_BLOCKS];
	};

	// ---------------------------------------------------------------------------------------------------------

	class ParameterBlockContainerDynamic : public ParameterBlockContainer
	{
	public:

		ParameterBlockContainerDynamic(cr::size_t maxParameterBlocks)
		: ParameterBlockContainer(new ParameterBlockHandle[maxParameterBlocks], maxParameterBlocks)
		{
		}
	};
}